<template>
  <FaLayout class="page" :right="240" :left="240">
    <AppHeader slot="header" />

    <FaPanel slot="left" title="控件填写" style="height: 100%">
      <FaWidgetFill ref="widgetFill" :viewer="viewer" @field-click="onFieldClick" />

      <footer v-if="widgetFill" slot="footer" class="widget-fill-ft">
        <ElButton @click="() => widgetFill?.clearValidate()">清除校验</ElButton>
        <ElButton type="primary" @click="() => widgetFill?.validate()">校验</ElButton>
      </footer>
    </FaPanel>

    <FaContract
      ref="viewer"
      :docs="docs"
      :doc-index.sync="docIndex"
      widget
      riding
      :widgets="widgets"
      :seals="signs.seals"
      :signatures="signs.signatures"
      :sign-options="signOptions"
      :widget-actor-required="widgetActorRequired"
      :attachment-upload="attachmentUpload"
      :image-upload="imageUpload"
      :widget-source-loader="widgetSourceLoader"
      @widgets-click="onWidgetsClick"
    >
      <template #page="{ page }">
        <WidgetGrid v-if="page.p === 0" title="签署控件" :list="signControls" />

        <WidgetGrid v-else-if="page.p === 1" title="填写控件" :list="fillControls" />

        <WidgetGrid v-else-if="page.p === 2" title="填写控件 - 纵向展示" :list="fillControlsV" vertical />
      </template>
    </FaContract>

    <template #right>
      <FaPanel :title="`设置${activeWidget.option.name}`" v-if="activeWidget" @click.stop.native style="height: 100%">
        <FaWidgetSetting :viewer="viewer" :data="activeWidget" :actors="actors" />
      </FaPanel>

      <FaThumbs v-show="!activeWidget" :viewer="viewer" :docs="docs" :doc-index.sync="docIndex" />
    </template>
  </FaLayout>
</template>

<script lang="ts">
import { computed, defineComponent, Ref, ref, reactive } from 'vue'
import {
  WidgetMode,
  ActorData,
  Widget,
  DocData,
  Viewer,
  createId,
  WidgetStyle,
  WidgetOption,
  WidgetType,
  WidgetKind,
  WidgetData,
  FaWidgetFill,
  SignOptions,
  WidgetSource
} from 'fdd-contract'
import AppHeader from '../components/AppHeader.vue'
import WidgetGrid from '../components/WidgetGrid.vue'
import { mockAjax } from '../utils'
import { getDateSignImg, signs } from '../utils/mock'

/** 所有控件选项列表 */
const allOptions = Widget.getWidgetOptions()

/** 控件值 */
const widgetValueMap = new Map([
  [
    WidgetType.SIGNATURE,
    {
      sign: signs.signatures[0]
    }
  ],
  [
    WidgetType.SEAL,
    {
      sign: signs.seals[0]
    }
  ],
  [
    WidgetType.REMARK,
    (mode: WidgetMode) =>
      mode === WidgetMode.DONE
        ? {
            value: '这个是签署备注的内容'
          }
        : {}
  ],
  [
    WidgetType.INPUT,
    {
      value: '这个是单行文本内容'
    }
  ],
  [
    WidgetType.TEXTAREA,
    {
      value: '这个是多行文本内容，这个是多行文本内容，这个是多行文本内容'
    }
  ],
  [
    WidgetType.CHECKBOX,
    {
      required: false
    }
  ],
  [
    WidgetType.NUMBER,
    {
      value: '123456'
    }
  ],
  [
    WidgetType.ID,
    {
      value: '440306202203263371'
    }
  ],
  [
    WidgetType.DATE_FILL,
    {
      value: '2022年03月26日'
    }
  ],
  [
    WidgetType.IMAGE,
    {
      image: {
        src: 'https://cdn.fadada.com/dist/static/portal/img/products/saas/saasimg01.png'
      },
      value: 'saasimg01'
    } as WidgetData
  ],
  [
    WidgetType.CHECKBOX,
    {
      value: true as unknown as string
    }
  ],
  [
    WidgetType.RADIO_GROUP,
    {
      checkOptions: [
        {
          label: '单选选项 - 1',
          value: true
        },
        {
          label: '单选选项 - 2'
        }
      ]
    }
  ],
  [
    WidgetType.CHECKBOX_GROUP,
    {
      checkOptions: [
        {
          label: '多选选项 - 1'
        },
        {
          label: '多选选项 - 2',
          value: true
        }
      ]
    }
  ],
  [
    WidgetType.SELECT,
    {
      value: '下拉选项 - 2',
      selectOptions: ['下拉选项 - 1', '下拉选项 - 2']
    }
  ],
  [
    WidgetType.TABLE,
    {
      tableOptions: {
        cols: 4
      }
    }
  ]
] as [WidgetType, WidgetData | ((mode: WidgetMode) => WidgetData | undefined)][])

/** 根据选项生成控件数据 */
function getWidgetData(item: WidgetOption, mode: WidgetMode, actors: ActorData[], doc: DocData, p = 0) {
  const { type } = item

  let extra = widgetValueMap.get(type)

  if (typeof extra === 'function') {
    extra = extra(mode)
  } else {
    if (mode === WidgetMode.SET) extra = undefined
  }

  return {
    type,
    name: `${item.name}-${mode}`,
    mode,
    docId: doc.id,
    p,
    actor: actors[allOptions.indexOf(item)],
    ...extra
  } as WidgetData
}

/** 生成控件 */
function createWidgets(options: WidgetOption[], actors: ActorData[], doc: DocData, p = 0, vertical = false) {
  const widgetModes = [WidgetMode.SET, WidgetMode.USE, WidgetMode.VIEW, WidgetMode.DONE]
  const docWidth = doc.pages[p].w
  const left = 140
  const top = 108
  const cellWidth = (docWidth - left - 20) / widgetModes.length

  if (!vertical) {
    return widgetModes.reduce((widgets, mode, index) => {
      let t = top

      widgets.push(
        ...options.map((item, i) => {
          const h = item.height + 40 - 1
          const oy = t + h / 2

          t += h

          return new Widget({
            ...getWidgetData(item, mode, actors, doc, p),
            ox: left + cellWidth * (index + 0.5),
            oy
          })
        })
      )
      return widgets
    }, [] as Widget[])
  }

  /** 纵向 */
  let vt = 70

  return options.reduce((widgets, item, index) => {
    vt += 32

    widgets.push(
      ...widgetModes.map((mode, i) => {
        const h = item.height + 80 - 1
        const oy = vt + h / 2

        vt += h

        return new Widget({
          ...getWidgetData(item, mode, actors, doc, p),
          x: left + 40,
          oy
        })
      })
    )
    return widgets
  }, [] as Widget[])
}

/** 获取控件数据 */
function getWidgets(actors: ActorData[], doc: DocData) {
  /** 签署控件选项 */
  const signControls = allOptions.filter(item => item.style === WidgetStyle.SIGN)

  /** 尺寸较大需要垂直展示的填写控件 */
  const fillVertical = [WidgetType.TABLE]

  /** 填写控件选项 */
  const fillControls = allOptions.filter(item => item.style === WidgetStyle.FILL && !fillVertical.includes(item.type))

  /** 填写控件选项 - 垂直展示 */
  const fillControlsV = allOptions.filter(item => item.style === WidgetStyle.FILL && fillVertical.includes(item.type))

  /** 控件 */
  const widgets = ref([
    ...createWidgets(signControls, actors, doc),
    ...createWidgets(fillControls, actors, doc, 1),
    ...createWidgets(fillControlsV, actors, doc, 2, true),

    new Widget({
      name: '骑缝控件-设置',
      type: WidgetType.SEAL,
      mode: WidgetMode.SET,
      kind: WidgetKind.RIDING,
      docId: doc.id,
      actor: actors[0],
      oy: 120
    }),

    new Widget({
      name: '骑缝控件-使用',
      type: WidgetType.SEAL,
      mode: WidgetMode.USE,
      kind: WidgetKind.RIDING,
      docId: doc.id,
      actor: actors[1],
      oy: 360,
      sign: signs.seals[2]
    }),

    new Widget({
      name: '骑缝控件-已完成',
      type: WidgetType.SEAL,
      mode: WidgetMode.DONE,
      kind: WidgetKind.RIDING,
      docId: doc.id,
      actor: actors[2],
      oy: 600,
      sign: signs.seals[0]
    })
  ])

  return {
    /** 控件 */
    widgets,

    /** 签署控件选项 */
    signControls,

    /** 填写控件选项 */
    fillControls,

    /** 填写控件选项 - 垂直展示 */
    fillControlsV
  }
}

/** 控件状态 */
export default defineComponent({
  name: 'WidgetStatus',
  components: { AppHeader, WidgetGrid },

  setup() {
    /** 合同控件 */
    const viewer = ref(null) as Ref<Viewer | null>

    /** 控件表单填写 */
    const widgetFill = ref(null) as Ref<InstanceType<typeof FaWidgetFill> | null>

    /** 参与方 */
    const actors = Array.from(
      new Array(16),
      (item, index) =>
        ({
          id: createId(),
          name: `参与方${index + 1}号`,
          index,
          sign: true,
          fill: true
        } as ActorData)
    )

    /** 文档 */
    const doc: DocData = {
      id: createId(),
      name: '控件展示文档',
      pages: [
        {
          p: 0,
          w: 1000,
          h: 800
        },
        {
          p: 1,
          w: 1000,
          h: 1200
        },
        {
          p: 2,
          w: 1000,
          h: 1200
        }
      ]
    }

    return {
      /** 合同控件 */
      viewer,

      /** 控件表单填写 */
      widgetFill,

      /** 文档列表 */
      docs: [doc],

      /** 参与方 */
      actors,

      /** 签章信息 */
      signs,

      /** 控件列表 */
      ...getWidgets(actors, doc),

      /** 当前文档索引 */
      docIndex: ref(0),

      /** 激活的控件 */
      activeWidget: computed(() => viewer.value?.activeWidget || null),

      /** 签章配置选项 */
      signOptions: reactive({
        signGlobal: true,
        signResizable: true,
        dateSignSrc: getDateSignImg
      } as SignOptions),

      /** 参与方是否必填 */
      widgetActorRequired: (widget: Widget) => widget.isSign,

      /** 附件上传 */
      attachmentUpload(file: File) {
        return mockAjax(() => ({
          id: createId(),
          fileName: file.name
        }))
      },

      /** 图片上传 */
      async imageUpload(file: File) {
        const src = URL.createObjectURL(file)

        return mockAjax(() => ({
          id: createId(),
          fileName: file.name,
          src
        }))
      },

      /** 控件数据来源加载 */
      widgetSourceLoader() {
        console.log('加载中！！！')
        return mockAjax(() => ({
          /** 认证姓名 */
          [WidgetSource.CERTIFIED_NAME]: '张三',
          /** 认证身份证 */
          [WidgetSource.CERTIFIED_ID]: '440306202203263371',
          /** 认证证件号 */
          [WidgetSource.CERTIFIED_CREDENTIAL]: 'B44030656X',
          /** 认证企业名称 */
          [WidgetSource.CERTIFIED_CORP_NAME]: '深圳市法大大科技有限公司',
          /** 统一社会信用代码 */
          [WidgetSource.CERTIFIED_CORP_USCC]: '91110000XYU26XND6Y'
        }))
      },

      /** 控件点击 */
      onWidgetsClick(widgets: Widget[], e: MouseEvent) {
        console.log(`点击了控件：`, widgets)
      },

      /** 填写表单控件字段点击 */
      onFieldClick(widget: Widget, e: MouseEvent) {
        console.log(`点击了控件字段：`, widget)
      }
    }
  }
})
</script>

<style lang="scss" scoped>
.widget-fill-ft {
  padding: 8px 16px;
  text-align: right;
  border-top: $border-solid;
}
</style>
